/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using VSLangProj80;
using EnvDTE;
using System.Collections.ObjectModel;
using VSLangProj;
using DaveSexton.DocProject.Engine;
using DaveSexton.DocProject.Sandcastle.Resources;

namespace DaveSexton.DocProject.Sandcastle
{
	/// <summary>
	/// Encapsulates the settings used by the <see cref="SandcastleBuildEngine" />, which includes some of the values for the commandline 
	/// arguments of several of the Sandcastle utility programs and path information to the various resources required for the build.
	/// </summary>
	/// <remarks>
	/// This class is not thread-safe.
	/// </remarks>
	public class SandcastleSettings : BuildSettings
	{
		#region Public Properties
		public static readonly string DefaultRelativeWorkingDirectory = "buildhelp";
		public static readonly string DefaultRelativeAssemblerWorkingDirectory = "assembler";
		public static readonly string DefaultRelativeAssemblerOutputDirectory = "Output";
		public static readonly string DefaultRawReflectionFileName = "reflection.org";
		public static readonly string DefaultReflectionXmlFileName = "reflection.xml";
		public static readonly string DefaultProjectXmlFileName = "project.xml";
		public static readonly string DefaultMergedTocFileName = "merged_toc.xml";
		public static readonly string DefaultTocFileName = "toc.xml";
		public static readonly string DefaultTopicsFileName = "topics.xml";
		public static readonly string DefaultConceptualArtMapFileName = "conceptual_art.xml";
		public static readonly string DefaultConceptualSnippetsFileName = "conceptual_snippets.xml";
		public static readonly string DefaultConceptualProjectMetadataFileName = "conceptual_project.xml";
		public static readonly string DefaultConceptualVersionMetadataFileName = "conceptual_version.xml";
		public static readonly string DefaultGlobalMetadataFileName = "metadata.xml";
		public static readonly string DefaultLinksFileName = "links.xml";
		public static readonly string DefaultWorkingConceptualMetadataFolderName = "XmlComp";
		public static readonly string DefaultWorkingConceptualFolderName = "DdueXml";
		public static readonly string DefaultTopicsHtmlFolderName = "Html";
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "xHtml")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultSpecialHelp2xHtmlTopicsFolderName = "MSHelp2";
		public static readonly string DefaultConceptualBuildManifestFileName = "conceptual_manifest.xml";
		public static readonly string DefaultReferenceBuildManifestFileName = "manifest.xml";
		public static readonly string DefaultDynamicFiltersFileName = "dynamicFilters.xml";
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId = "Member")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hx")]
		public static readonly string TocToHxSContentsTransformationFileName = "TocToHxSContents.xsl";
		public static readonly string ReflectionToManifestTransformationFileName = "ReflectionToManifest.xsl";
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId = "Member")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp1xProjectConfigFileName = "help1x.config";
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp2xProjectConfigFileName = "help2x.xslt";
		public static readonly string DefaultVersionsFileName = "versions.xml";
		public static readonly string DefaultVersionsContentFileName = "version_content.xml";
		public static readonly string DefaultVersionsConfigFileName = "versions.config";
		public static readonly string MergeDuplicatesTransformationFileName = "MergeDuplicates.xsl";
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp2xFilesCollectionFileName = "files.HxF";
		/// <summary>index_a.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp2xAssociativeIndexFileName = "index_a.HxK";
		/// <summary>index_f.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp2xContextSensitiveIndexFileName = "index_f.HxK";
		/// <summary>index_b.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp2xDynamicLinkIndexFileName = "index_b.HxK";
		/// <summary>index_k.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp2xKeywordIndexFileName = "index_k.HxK";
		/// <summary>index_s.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp2xSearchWindowIndexFileName = "index_s.HxK";
		/// <summary>index_n.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public static readonly string DefaultHelp2xNamedUrlIndexFileName = "index_n.HxK";
		public static readonly string DefaultMSHelp2AboutImageFileName = "MSHelp2AboutImage.jpg";
		public static readonly string DefaultProjectConfigurationDirectory = "Projects";
		public static readonly string DefaultBibliographyFileName = "bibliography.xml";
		public static readonly string DefaultTokensFileName = "tokens.xml";

		public override IEnumerable<SystemPath> Targets
		{
			get
			{
				if (Engine.Options.Help1xProject.OutputEnabled)
					yield return new SystemPath(CompiledHelp1xFile, false, false);

				if (Engine.Options.Help2xProject.OutputEnabled)
					yield return new SystemPath(CompiledHelp2xFile, false, false);
			}
		}

		public override string RelativeWorkingDirectory
		{
			get
			{
				return DefaultRelativeWorkingDirectory;
			}
		}

		public override string RelativeTargetDirectory
		{
			get
			{
				return SandcastleBuildEngineProvider.ProjectPaths.RelativeHelpRoot;
			}
		}

		public override string RelativeWorkingXmlDocumentationPath
		{
			get
			{
				return Path.Combine(DefaultRelativeAssemblerWorkingDirectory, "Comments");
			}
		}

		public new SandcastleBuildEngine Engine
		{
			get
			{
				return (SandcastleBuildEngine) base.Engine;
			}
		}

		public virtual string DocumentationSetFileName
		{
			get
			{
				return PathFormat.EnsureFileName(Engine.Options.DocumentationSetName);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string Help1xProjectConfigFileName
		{
			get
			{
				return DefaultHelp1xProjectConfigFileName;
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string RelativeHelp1xProjectConfigFile
		{
			get
			{
				return Path.Combine(RelativeProjectConfigurationDirectory, Help1xProjectConfigFileName);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string Help1xProjectConfigFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeHelp1xProjectConfigFile);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string Help2xProjectConfigFileName
		{
			get
			{
				return DefaultHelp2xProjectConfigFileName;
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string Help2xProjectConfigFile
		{
			get
			{
				return Path.Combine(ProjectConfigurationDirectory, Help2xProjectConfigFileName);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string Help2xFilesCollectionFileName
		{
			get
			{
				return DefaultHelp2xFilesCollectionFileName;
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string Help2xFilesCollectionFile
		{
			get
			{
				return Path.Combine(TargetDirectory, Help2xFilesCollectionFileName);
			}
		}

		/// <summary>index_a.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string Help2xAssociativeIndexFileName
		{
			get
			{
				return DefaultHelp2xAssociativeIndexFileName;
			}
		}

		/// <summary>index_a.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string Help2xAssociativeIndexFile
		{
			get
			{
				return Path.Combine(TargetDirectory, Help2xAssociativeIndexFileName);
			}
		}

		/// <summary>index_f.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string Help2xContextSensitiveIndexFileName
		{
			get
			{
				return DefaultHelp2xContextSensitiveIndexFileName;
			}
		}

		/// <summary>index_f.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string Help2xContextSensitiveIndexFile
		{
			get
			{
				return Path.Combine(TargetDirectory, Help2xContextSensitiveIndexFileName);
			}
		}

		/// <summary>index_b.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string Help2xDynamicLinkIndexFileName
		{
			get
			{
				return DefaultHelp2xDynamicLinkIndexFileName;
			}
		}

		/// <summary>index_b.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string Help2xDynamicLinkIndexFile
		{
			get
			{
				return Path.Combine(TargetDirectory, Help2xDynamicLinkIndexFileName);
			}
		}

		/// <summary>index_k.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string Help2xKeywordIndexFileName
		{
			get
			{
				return DefaultHelp2xKeywordIndexFileName;
			}
		}

		/// <summary>index_k.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string Help2xKeywordIndexFile
		{
			get
			{
				return Path.Combine(TargetDirectory, Help2xKeywordIndexFileName);
			}
		}

		/// <summary>index_s.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string Help2xSearchWindowIndexFileName
		{
			get
			{
				return DefaultHelp2xSearchWindowIndexFileName;
			}
		}

		/// <summary>index_s.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string Help2xSearchWindowIndexFile
		{
			get
			{
				return Path.Combine(TargetDirectory, Help2xSearchWindowIndexFileName);
			}
		}

		/// <summary>index_n.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")]
		public virtual string Help2xNamedUrlIndexFileName
		{
			get
			{
				return DefaultHelp2xNamedUrlIndexFileName;
			}
		}

		/// <summary>index_n.HxK</summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")]
		public string Help2xNamedUrlIndexFile
		{
			get
			{
				return Path.Combine(TargetDirectory, Help2xNamedUrlIndexFileName);
			}
		}

		public virtual string VersionsFileName
		{
			get
			{
				return DefaultVersionsFileName;
			}
		}

		public string RelativeVersionsFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, VersionsFileName);
			}
		}

		public string VersionsFile
		{
			get
			{
				return Path.Combine(SettingsDirectory, VersionsFileName);
			}
		}

		public virtual string VersionsContentFileName
		{
			get
			{
				return DefaultVersionsContentFileName;
			}
		}

		public string VersionsContentFile
		{
			get
			{
				return System.IO.Path.Combine(BuildAssemblerWorkingDirectory, VersionsContentFileName);
			}
		}

		public virtual string VersionsConfigFileName
		{
			get
			{
				return DefaultVersionsConfigFileName;
			}
		}

		public string VersionsConfigFile
		{
			get
			{
				return System.IO.Path.Combine(WorkingDirectory, VersionsConfigFileName);
			}
		}

		public virtual string TopicsHtmlFolderName
		{
			get
			{
				return DefaultTopicsHtmlFolderName;
			}
		}

		public string RelativeTopicsHtmlDirectory
		{
			get
			{
				return Path.Combine(RelativeTopicsDirectory, TopicsHtmlFolderName);
			}
		}

		public string TopicsHtmlDirectory
		{
			get
			{
				return Path.Combine(TopicsDirectory, TopicsHtmlFolderName);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "xHtml")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string SpecialHelp2xHtmlTopicsFolderName
		{
			get
			{
				return DefaultSpecialHelp2xHtmlTopicsFolderName;
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "xHtml")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string SpecialHelp2xHtmlTopicsDirectory
		{
			get
			{
				return Path.Combine(TopicsHtmlDirectory, SpecialHelp2xHtmlTopicsFolderName);
			}
		}

		public virtual string MSHelp2AboutImageFileName
		{
			get
			{
				return DefaultMSHelp2AboutImageFileName;
			}
		}

		public virtual string ConceptualArtMapName
		{
			get
			{
				return DefaultConceptualArtMapFileName;
			}
		}

		public virtual string RelativeConceptualArtMapFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, ConceptualArtMapName);
			}
		}

		public string ConceptualArtMapFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeConceptualArtMapFile);
			}
		}

		public virtual string ConceptualSnippetsFileName
		{
			get
			{
				return DefaultConceptualSnippetsFileName;
			}
		}

		public virtual string RelativeConceptualSnippetsFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, ConceptualSnippetsFileName);
			}
		}

		public string ConceptualSnippetsFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeConceptualSnippetsFile);
			}
		}

		public virtual string TokensFileName
		{
			get
			{
				return DefaultTokensFileName;
			}
		}

		public virtual string RelativeTokensFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, TokensFileName);
			}
		}

		public string TokensFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeTokensFile);
			}
		}

		public virtual string ConceptualProjectMetadataFileName
		{
			get
			{
				return DefaultConceptualProjectMetadataFileName;
			}
		}

		public virtual string RelativeConceptualProjectMetadataFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, ConceptualProjectMetadataFileName);
			}
		}

		public string ConceptualProjectMetadataFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeConceptualProjectMetadataFile);
			}
		}

		public virtual string ConceptualVersionMetadataFileName
		{
			get
			{
				return DefaultConceptualVersionMetadataFileName;
			}
		}

		public virtual string RelativeConceptualVersionMetadataFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, ConceptualVersionMetadataFileName);
			}
		}

		public string ConceptualVersionMetadataFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeConceptualVersionMetadataFile);
			}
		}

		public virtual string GlobalMetadataFileName
		{
			get
			{
				return DefaultGlobalMetadataFileName;
			}
		}

		public virtual string RelativeGlobalMetadataFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, GlobalMetadataFileName);
			}
		}

		public string GlobalMetadataFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeGlobalMetadataFile);
			}
		}

		public virtual string BibliographyFileName
		{
			get
			{
				return DefaultBibliographyFileName;
			}
		}

		public virtual string RelativeBibliographyFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, BibliographyFileName);
			}
		}

		public string BibliographyFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeBibliographyFile);
			}
		}

		public virtual string LinksFileName
		{
			get
			{
				return DefaultLinksFileName;
			}
		}

		public virtual string RelativeLinksFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, LinksFileName);
			}
		}

		public string LinksFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeLinksFile);
			}
		}

		public virtual string RelativeProjectConfigurationDirectory
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, DefaultProjectConfigurationDirectory);
			}
		}

		public string ProjectConfigurationDirectory
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeProjectConfigurationDirectory);
			}
		}

		public virtual string RelativeSettingsDirectory
		{
			get
			{
				return SandcastleBuildEngineProvider.ProjectPaths.RelativeSettingsPath;
			}
		}

		public string SettingsDirectory
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeSettingsDirectory);
			}
		}

		public virtual string RelativeTopicsDirectory
		{
			get
			{
				return SandcastleBuildEngineProvider.ProjectPaths.RelativeTopicsPath;
			}
		}

		public string TopicsDirectory
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeTopicsDirectory);
			}
		}

		public virtual string ReferenceBuildManifestFileName
		{
			get
			{
				return DefaultReferenceBuildManifestFileName;
			}
		}

		public string ReferenceBuildManifestFile
		{
			get
			{
				return Path.Combine(WorkingDirectory, ReferenceBuildManifestFileName);
			}
		}

		public virtual string ConceptualBuildManifestFileName
		{
			get
			{
				return DefaultConceptualBuildManifestFileName;
			}
		}

		public string ConceptualBuildManifestFile
		{
			get
			{
				return Path.Combine(WorkingDirectory, ConceptualBuildManifestFileName);
			}
		}

		public virtual string WorkingConceptualMetadataFolderName
		{
			get
			{
				return DefaultWorkingConceptualMetadataFolderName;
			}
		}

		public string WorkingConceptualMetadataDirectory
		{
			get
			{
				return Path.Combine(BuildAssemblerWorkingDirectory, WorkingConceptualMetadataFolderName);
			}
		}

		public virtual string WorkingConceptualFolderName
		{
			get
			{
				return DefaultWorkingConceptualFolderName;
			}
		}

		public string WorkingConceptualDirectory
		{
			get
			{
				return Path.Combine(BuildAssemblerWorkingDirectory, WorkingConceptualFolderName);
			}
		}

		/// <summary>
		/// Gets the path to the content folder, which contains item-based XML files that provide localizable text and/or 
		/// HTML content for sections of API topics that are generated by Sandcastle.
		/// </summary>
		/// <remarks>
		/// This propery has a preference for returning a relative path, if <see cref="RelativePresentationPath"/> 
		/// is not <see langword="null"/>.
		/// </remarks>
		public string ContentDirectory
		{
			get
			{
				return Path.Combine(RelativePresentationPath ?? PresentationPath, presentation.ContentDirectory);
			}
		}

		public string SharedContentDirectory
		{
			get
			{
				return Path.Combine(RelativeSharedPresentationPath ?? SharedPresentationPath, presentation.ContentDirectory);
			}
		}

		public virtual string DynamicFiltersFileName
		{
			get
			{
				return DefaultDynamicFiltersFileName;
			}
		}

		public string RelativeDynamicFiltersFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, DynamicFiltersFileName);
			}
		}

		public string DynamicFiltersFile
		{
			get
			{
				return Path.Combine(SettingsDirectory, DynamicFiltersFileName);
			}
		}

		public virtual string MergedTocFileName
		{
			get
			{
				return DefaultMergedTocFileName;
			}
		}

		public string MergedTocFile
		{
			get
			{
				return Path.Combine(WorkingDirectory, MergedTocFileName);
			}
		}

		public virtual string TocFileName
		{
			get
			{
				return DefaultTocFileName;
			}
		}

		public string TocFile
		{
			get
			{
				return Path.Combine(WorkingDirectory, TocFileName);
			}
		}

		public virtual string TopicsFileName
		{
			get
			{
				return DefaultTopicsFileName;
			}
		}

		public string RelativeTopicsFile
		{
			get
			{
				return Path.Combine(RelativeSettingsDirectory, TopicsFileName);
			}
		}

		public string TopicsFile
		{
			get
			{
				return Path.Combine(SettingsDirectory, TopicsFileName);
			}
		}

		public string TargetReflectionXmlFile
		{
			get
			{
				return Path.Combine(BuildAssemblerWorkingDirectory, ReflectionXmlFileName);
			}
		}

		public string ReflectionXmlFile
		{
			get
			{
				return Path.Combine(WorkingDirectory, ReflectionXmlFileName);
			}
		}

		public virtual string ReflectionXmlFileName
		{
			get
			{
				return DefaultReflectionXmlFileName;
			}
		}

		/// <summary>
		/// Gets the relative path of the Sandcastle configuration directory for the project.
		/// </summary>
    public virtual string RelativeConfigurationPath
		{
			get
			{
				return SandcastleBuildEngineProvider.ProjectPaths.Configuration;
			}
		}

		public virtual string RelativeExternalXmlDocumentationPath
		{
			get
			{
				return SandcastleBuildEngineProvider.ProjectPaths.RelativeCommentsPath;
			}
		}

		public string ExternalXmlDocumentationPath
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeExternalXmlDocumentationPath);
			}
		}

		public virtual string ProjectXmlFileName
		{
			get
			{
				return DefaultProjectXmlFileName;
			}
		}

		public virtual string RelativeProjectXmlFile
		{
			get
			{
				return Path.Combine(RelativeExternalXmlDocumentationPath, ProjectXmlFileName);
			}
		}

		public string ProjectXmlFile
		{
			get
			{
				return Path.Combine(TargetDirectory, RelativeProjectXmlFile);
			}
		}

		public bool UseHelp1HtmlToCompileHelp2
		{
			get
			{
				return Engine.Options.Help1xProject.OutputEnabled && Help1ConfigurationFile.Equals(Help2ConfigurationFile, StringComparison.OrdinalIgnoreCase);
			}
		}

		public bool HtmlHelpWorkshopFilesRequired
		{
			get
			{
				return Project.IsDocSite;
			}
		}

		public string Help1ConfigurationFile
		{
			get
			{
				return Path.Combine(ConfigurationPath, Engine.Options.Help1xConfigFileName);
			}
		}

		public string Help2ConfigurationFile
		{
			get
			{
				return Path.Combine(ConfigurationPath, Engine.Options.Help2xConfigFileName);
			}
		}

		public string Help1ConceptualConfigurationFile
		{
			get
			{
				return Path.Combine(ConfigurationPath, Engine.Options.Help1xConceptualConfigFileName);
			}
		}

		public string Help2ConceptualConfigurationFile
		{
			get
			{
				return Path.Combine(ConfigurationPath, Engine.Options.Help2xConceptualConfigFileName);
			}
		}

		/// <summary>
		/// Gets the file name of the compiled help 1.x file (.chm) built by the engine.
		/// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string CompiledHelp1xFileName
		{
			get
			{
				return DocumentationSetFileName + ".chm";
			}
		}

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string CompiledHelp1xFile
		{
			get
			{
				return Path.Combine(ProjectDirectory, RelativeCompiledHelp1xFile);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string RelativeCompiledHelp1xFile
		{
			get
			{
				return Path.Combine(RelativeCompiledHelp1xDirectory, CompiledHelp1xFileName);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string RelativeCompiledHelp1xDirectory
		{
			get
			{
				if (Project.IsDocSite)
					return Path.Combine(RelativeTargetDirectory, "bin");
				else
					return RelativeProjectOutputDirectory;
			}
		}

		/// <summary>
		/// Gets the file name of the compiled help 2.x file (.HxS) built by the engine.
		/// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string CompiledHelp2xFileName
		{
			get
			{
				/* 
				 * HACK: An issue has been identified that when using the Help Integration Wizard to 
				 * install an .HxS that has spaces in its file name, the help collection will appear 
				 * to be installed successfully but will not show up in Visual Studio's help.
				 * Therefore, the file name is formatted to ensure that no spaces exist.
				 * http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1446248&SiteID=1
				 */
				return DocumentationSetFileName.Replace(" ", "") + ".HxS";
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string CompiledHelp2xFile
		{
			get
			{
				return Path.Combine(ProjectDirectory, RelativeCompiledHelp2xFile);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public string RelativeCompiledHelp2xFile
		{
			get
			{
				return Path.Combine(RelativeCompiledHelp2xDirectory, CompiledHelp2xFileName);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "x")]
		public virtual string RelativeCompiledHelp2xDirectory
		{
			get
			{
				if (Project.IsDocSite)
					return Path.Combine(RelativeTargetDirectory, "bin");
				else
					return RelativeProjectOutputDirectory;
			}
		}

		public string BuildAssemblerWorkingDirectory
		{
			get
			{
				return Path.Combine(WorkingDirectory, DefaultRelativeAssemblerWorkingDirectory);
			}
		}

		public string BuildAssemblerRelativeWorkingDirectory
		{
			get
			{
				return Path.Combine(RelativeWorkingDirectory, DefaultRelativeAssemblerWorkingDirectory);
			}
		}

		public string BuildAssemblerOutputDirectory
		{
			get
			{
				return Path.Combine(Path.Combine(WorkingDirectory, DefaultRelativeAssemblerWorkingDirectory), DefaultRelativeAssemblerOutputDirectory);
			}
		}

		public string BuildAssemblerRelativeOutputDirectory
		{
			get
			{
				return Path.Combine(BuildAssemblerRelativeWorkingDirectory, DefaultRelativeAssemblerOutputDirectory);
			}
		}

		public bool BuildConceptualTopics
		{
			[System.Diagnostics.DebuggerHidden]
			get
			{
				return TopicManagement.TopicsDocument.HasConceptualTopics(TopicsFile);
			}
		}

		public bool BuildReferenceTopics
		{
			get
			{
				return Project.ProjectSources.Count > 0 || Project.ExternalSources.Count > 0;
			}
		}

		/// <summary>
		/// Gets the full path of the Sandcastle configuration directory for the project.
		/// </summary>
		public string ConfigurationPath
		{
			get
			{
				return Path.Combine(TargetDirectory, SandcastleBuildEngineProvider.ProjectPaths.Configuration);
			}
		}

		/// <summary>
		/// Gets the path to the folder that contains the Sandcastle executable utilities.
		/// </summary>
    public virtual string ToolsPath
		{
			get
			{
				return SandcastleBuildEngineProvider.Paths.Tools;
			}
		}

		public string PresentationTransformsPath
		{
			get
			{
				return Path.Combine(TargetDirectory, SandcastleBuildEngineProvider.ProjectPaths.Transforms);
			}
		}

		public string MRefBuilderConfigSwitch
		{
			get
			{
				return "/config:\"" + Path.Combine(ConfigurationPath, Engine.Options.MRefBuilderConfigurationFileName) + "\"";
			}
		}

		/// <summary>
		/// Gets the full path to the shared folder that contains the elements to control the visual presentation of the compiled documentation.
		/// </summary>
		public string SharedPresentationPath
		{
			get
			{
				return sharedPresentationPath;
			}
		}

		/// <remarks>
		/// This property will return <strong>null</strong> if the <see cref="SharedPresentationPath" /> property is initialized to an absolute path.
		/// </remarks>
		public string RelativeSharedPresentationPath
		{
			get
			{
				return relativeSharedPresentationPath;
			}
		}

		/// <summary>
		/// Gets the full path to the folder that contains the elements to control the visual presentation of the compiled documentation.
		/// </summary>
		public string PresentationPath
		{
			get
			{
				return presentationPath;
			}
		}

		/// <remarks>
		/// This property will return <strong>null</strong> if the <see cref="PresentationPath" /> property is initialized to an absolute path.
		/// </remarks>
		public string RelativePresentationPath
		{
			get
			{
				return relativePresentationPath;
			}
		}

		/// <summary>
		/// Gets or sets the path to the folder that contains the Sandcastle XML transformations (XSLT).
		/// </summary>
    public virtual string XslTransformationsPath
		{
			get
			{
				return SandcastleBuildEngineProvider.Paths.Transforms;
			}
		}

		/// <summary>
		/// Gets or sets the full path and file name of the <b>Microsoft Html Help Workshop</b> program that will build the compiled help 1.x file (.chm).
		/// </summary>
    public virtual string HtmlHelpWorkshop
		{
			get
			{
				return SandcastleBuildEngineProvider.Paths.HtmlHelpWorkshop;
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Chm")]
		public virtual string ChmBuilderProgram
		{
			get
			{
				return Path.Combine(ToolsPath, "ChmBuilder");
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dbcs")]
		public virtual string DbcsFixProgram
		{
			get
			{
				return Path.Combine(ToolsPath, "DBCSFix");
			}
		}

		public virtual string AppLocaleProgram
		{
			get
			{
				return Environment.ExpandEnvironmentVariables(@"%windir%\apppatch\AppLoc.exe");
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Lcid")]
		public virtual int Lcid
		{
			get
			{
				// TODO: localization
				return 1033;	// en-US
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Chm")]
		public string ChmBuilderMetadataSwitch
		{
			get
			{
				if (Project.IsDocSite || UseHelp1HtmlToCompileHelp2)
					return "/metadata+";
				else
					return "/metadata-";
			}
		}

		/// <summary>
		/// Gets ths scope switch for the MRefBuilder program based on the value of the <see cref="BuildSettings.Scope" /> property.
		/// </summary>
		/// <seealso cref="BuildSettings.Scope" />
		public string ScopeSwitch
		{
			get
			{
				if (Scope == DocumentationScope.Complete)
					return "/internal+";
				else
					return "/internal-";
			}
		}

		/// <summary>
		/// Gets the path and name of the <b>MRefBuilder</b> program in the <see cref="ToolsPath" /> directory.
		/// </summary>
		public string MRefBuilder
		{
			get
			{
				return Path.Combine(ToolsPath, "MRefBuilder");
			}
		}

		/// <summary>
		/// Gets the path and name of the <b>XslTransform</b> program in the <see cref="ToolsPath" /> directory.
		/// </summary>
		public string XslTransform
		{
			get
			{
				return Path.Combine(ToolsPath, "XslTransform");
			}
		}

		/// <summary>
		/// Gets the path and name of the <b>VersionBuilder</b> program in the <see cref="ToolsPath" /> directory.
		/// </summary>
		public string VersionBuilder
		{
			get
			{
				return Path.Combine(ToolsPath, "VersionBuilder");
			}
		}

		public string VersionBuilderConfigSwitch
		{
			get
			{
				return "/config:\"" + VersionsConfigFile + "\"";
			}
		}

		public Configuration.Presentation Presentation
		{
			get
			{
				return presentation;
			}
		}
		#endregion

		#region Private / Protected
		private readonly string presentationPath, relativePresentationPath, sharedPresentationPath, relativeSharedPresentationPath;
		private readonly Configuration.Presentation presentation;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="SandcastleSettings" /> class, initializing some of the settings based on the specified
		/// <paramref name="project" />.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
		public SandcastleSettings(IBuildEngine engine)
			: base(engine)
		{
			if (engine == null)
				throw new ArgumentNullException("engine");

			SandcastleBuildEngine sandcastle = engine as SandcastleBuildEngine;

			if (sandcastle == null)
				throw new ArgumentException(Errors.InvalidBuildEngineTypeSandcastle, "engine");

			presentation = SandcastleBuildEngineProvider.Presentations[sandcastle.Options.PresentationName];

			string path = sandcastle.Options.PresentationPath;

			if (!Path.IsPathRooted(path))
			{
				relativePresentationPath = path;
				path = sandcastle.Options.PresentationPathAbsolute;
			}

			presentationPath = path;

			path = SandcastleBuildEngineProvider.ProjectPaths.SharedPresentation;

			if (!string.IsNullOrEmpty(path) && !Path.IsPathRooted(path))
			{
				relativeSharedPresentationPath = path;
				path = Path.Combine(TargetDirectory, path);
			}

			sharedPresentationPath = path;
		}
		#endregion

		#region Methods
		public static void AddSourcesInto<T>(ICollection<string> assemblies, bool surroundAssembliesInQuotes, ICollection<string> reflectionFiles, bool surroundReflectionFilesInQuotes,
			IEnumerable<T> sources, Converter<T, SystemPath> converter)
		{
			if (assemblies == null)
				throw new ArgumentNullException("assemblies");

			if (reflectionFiles == null)
				throw new ArgumentNullException("reflectionFiles");

			if (sources == null)
				throw new ArgumentNullException("sources");

			if (converter == null)
				throw new ArgumentNullException("converter");

			foreach (T value in sources)
			{
				SystemPath source = converter(value);

				if (source == SystemPath.Empty)
					continue;

				// NOTE: MRefBuilder allows wildcards in a file name, but not a recursive directory wildcard in the path.
				// NOTE: All reflection files must be resolved by this method; i.e., paths with wildcards should not be added to the output collection.

				if (source.IsDirectory)
				{
					if (source.HasRecursiveDirectory)
					{
						foreach (SystemPath file in source.GetFiles("*.dll"))
							assemblies.Add((surroundAssembliesInQuotes) ? "\"" + file.Path + "\"" : file.Path);

						foreach (SystemPath file in source.GetFiles("*.exe"))
							assemblies.Add((surroundAssembliesInQuotes) ? "\"" + file.Path + "\"" : file.Path);
					}
					else
					{
						string input = source.CompleteCombineWith("*.dll");
						assemblies.Add((surroundAssembliesInQuotes) ? "\"" + input + "\"" : input);

						input = source.CompleteCombineWith("*.exe");
						assemblies.Add((surroundAssembliesInQuotes) ? "\"" + input + "\"" : input);
					}

					foreach (SystemPath file in source.GetFiles("*.org"))
						reflectionFiles.Add((surroundReflectionFilesInQuotes) ? "\"" + file.Path + "\"" : file.Path);
				}
				else if (source.IsAssembly)
				{
					if (source.HasRecursiveDirectory)
					{
						foreach (SystemPath file in source.GetFiles())
							assemblies.Add((surroundAssembliesInQuotes) ? "\"" + file.Path + "\"" : file.Path);
					}
					else
						assemblies.Add((surroundAssembliesInQuotes) ? "\"" + source.Path + "\"" : source.Path);
				}
				else if (source.HasFileExtension(".org"))
				{
					foreach (SystemPath file in source.GetFiles())
						reflectionFiles.Add((surroundReflectionFilesInQuotes) ? "\"" + file.Path + "\"" : file.Path);
				}
				else
					throw new InvalidOperationException(string.Format(System.Globalization.CultureInfo.CurrentCulture,
						Resources.Errors.InvalidSourceFile, source.Path));
			}
		}

		/// <summary>
		/// Creates a switch for the <see cref="XslTransform" /> utility that indicates the name of the transformation to be applied.
		/// </summary>
		/// <remarks>
		/// The string returned is in the following format: 
		/// <para>
		/// /xsl:&quot;{<paramref name="directory" />}\{<paramref name="xslTransformName" />}&quot;
		/// </para>
		/// </remarks>
		public static string CreateXslTransformSwitch(string directory, string xslTransformName)
		{
			if (string.IsNullOrEmpty(xslTransformName))
				throw new ArgumentException(Errors.NullOrEmpty, "xslTransformName");

			return "/xsl:\"" + Path.Combine(directory, xslTransformName) + "\"";
		}

		/// <summary>
		/// Creates a switch for the <see cref="XslTransform" /> utility that indicates the name of the transformation to be applied.
		/// </summary>
		/// <remarks>
		/// The string returned is in the following format: 
		/// <para>
		/// /xsl:&quot;{<see cref="XslTransformationsPath" />}\{<paramref name="xslTransformName" />}&quot;
		/// </para>
		/// </remarks>
		public string CreateXslTransformSwitch(string xslTransformName)
		{
			return CreateXslTransformSwitch(XslTransformationsPath, xslTransformName);
		}

		/// <param name="argumentList">Semi-colon delimited list of name=value pairs that can be used as xsl variable arguments for the <see cref="XslTransform"/> program.</param>
		public IEnumerable<string> CreateXslTransformArgumentSwitches(string argumentList)
		{
			return new MarshalByRefEnumerable<string>(CreateXslTransformArgumentSwitchesInternal, argumentList);
		}

		private IEnumerable<string> CreateXslTransformArgumentSwitchesInternal(object[] arguments)
		{
			string argumentList = (string) arguments[0];

			if (!string.IsNullOrEmpty(argumentList))
				foreach (string arg in argumentList.Split(';'))
					yield return "/arg:" + arg;
		}

		public string CreateDependencySwitch(IEnumerable<string> sources)
		{
			StringBuilder builder = new StringBuilder("/dep:");

			SandcastleProjectOptions options = (SandcastleProjectOptions) Project.Options;

			IList<SystemPath> missingDependencies = options.MissingDependencies;

			bool hasDependency = missingDependencies.Count > 0;

			// NOTE: MRefBuilder allows wildcards in a file name, but not a recursive directory wildcard in the path.

			foreach (SystemPath dependency in missingDependencies)
			{
				if (dependency.IsDirectory)
				{
					if (dependency.HasRecursiveDirectory)
					{
						foreach (string file in dependency.GetFiles("*.dll"))
							builder.AppendFormat("\"{0}\",", file);

						foreach (string file in dependency.GetFiles("*.exe"))
							builder.AppendFormat("\"{0}\",", file);
					}
					else
					{
						builder.AppendFormat("\"{0}\",", dependency.CombineWith("*.dll"));
						builder.AppendFormat("\"{0}\",", dependency.CombineWith("*.exe"));
					}
				}
				else if (!dependency.IsAssembly)
					throw new InvalidOperationException(string.Format(System.Globalization.CultureInfo.CurrentCulture, 
						Resources.Errors.InvalidDependency, dependency.CompletePath));
				else if (dependency.HasRecursiveDirectory)
				{
					foreach (string file in dependency.GetFiles())
						builder.AppendFormat("\"{0}\",", file);
				}
				else
					builder.AppendFormat("\"{0}\",", dependency.Path);
			}

			List<string> formattedSources = new List<string>(sources);
			for (int i = 0; i < formattedSources.Count; i++)
				formattedSources[i] = formattedSources[i].Trim('"');

			foreach (SystemPath dependency in ReferenceResolver.FindUniqueReferencesRecursive(ProjectDirectory, formattedSources))
			{
				builder.AppendFormat("\"{0}\",", Environment.ExpandEnvironmentVariables(dependency.Path));
				hasDependency = true;
			}

			if (!hasDependency)
				return null;

			// remove trailing comma
			builder.Remove(builder.Length - 1, 1);

			return builder.ToString();
		}
		#endregion
	}
}
